﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Text;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Http;
using Microsoft.EntityFrameworkCore;
using Z.EntityFramework;
using Z.EntityFramework.Extensions;
using Z.EntityFramework.Plus;
using CustomerAudit = Rbac.Project.Domain.Audit;

namespace Rabc.Project.Repositories
{
	/// <summary>
	/// 泛型类
	/// </summary>
	/// <typeparam name="TEntity"></typeparam>
	public class Repository<TEntity> : IRepository<TEntity> where TEntity : class, new()
    {
        private readonly RbacDbContext db;
        private readonly IHttpContextAccessor httpContext;

        public Repository(RbacDbContext db, IHttpContextAccessor httpContext)
        {
            this.db = db;
            this.httpContext = httpContext;
        }

        /// <summary>
        /// 添加
        /// </summary>
        /// <param name="entity"></param>
        /// <returns></returns>
        public TEntity Insert(TEntity entity)
        {
            db.Set<TEntity>().Add(entity);
            db.SaveChanges();
            return entity;
        }

        /// <summary>
        /// 异步添加
        /// </summary>
        /// <param name="entity"></param>
        /// <returns></returns>
        public async Task<TEntity> InsertAsync(TEntity entity)
        {
            Type type = entity.GetType();
            var PropCreateTime = type.GetProperties().FirstOrDefault(m => m.Name == nameof(CustomerAudit.CreateTime));
            if(PropCreateTime != null)
                PropCreateTime.SetValue(entity, DateTime.Now);

            var PropCreateName = type.GetProperties().FirstOrDefault(m => m.Name == nameof(CustomerAudit.CreateName));
            if (PropCreateName != null)
                PropCreateName.SetValue(entity, httpContext.HttpContext.User.Identity.Name);

            await db.Set<TEntity>().AddAsync(entity);
            await db.SaveChangesAsync();
            return entity;
        }

        /// <summary>
        /// 异步批量添加
        /// </summary>
        /// <param name="entity"></param>
        /// <returns></returns>
        public async Task<int> InsertManyAsync(List<TEntity> entity)
        {
            await db.Set<TEntity>().AddRangeAsync(entity);
            return await db.SaveChangesAsync();
        }

        /// <summary>
        /// 根据主键删除
        /// </summary>
        /// <param name="Id"></param>
        /// <returns></returns>
        public async Task<int> DeleteAsync(int Id)
        {
            Type type = typeof(TEntity);
            var PropIsDeleted = type.GetProperties().FirstOrDefault(m => m.Name == nameof(CustomerAudit.IsDeleted));
            
            //逻辑删除
            if(PropIsDeleted != null)
            {
                var Entity = await db.Set<TEntity>().FindAsync(Id);
                PropIsDeleted.SetValue(Entity, true);
                db.Set<TEntity>().Update(Entity);
                return await db.SaveChangesAsync();
            }
            else 
            { 
                var Entity = await db.Set<TEntity>().FindAsync(Id);
                db.Set<TEntity>().Remove(Entity);
                return await db.SaveChangesAsync();
            }
        }

        /// <summary>
        /// 按条件删除
        /// </summary>
        /// <param name="Id"></param>
        /// <returns></returns>
        public async Task<int> DeleteAsync(Expression<Func<TEntity, bool>> predicate)
        {
            return await db.Set<TEntity>().Where(predicate).DeleteAsync();

        }

        /// <summary>
        /// 批量删除
        /// </summary>
        /// <param name="Id"></param>
        /// <returns></returns>
        public async Task<int> DeleteAsync(List<TEntity> entities)
        {
            db.Set<TEntity>().RemoveRange(entities);
            return await db.SaveChangesAsync();
        }

        /// <summary>
        /// 更新
        /// </summary>
        /// <param name="entity"></param>
        /// <returns></returns>
        public async Task<TEntity> UpdateAsync(TEntity entity)
        {
            db.Set<TEntity>().Update(entity);
            await db.SaveChangesAsync();
            return entity;
        }

        /// <summary>
        /// 查询
        /// </summary>
        /// <param name="Id"></param>
        /// <returns></returns>
        public async Task<TEntity> FindAsync(int Id)
        {
            return await db.Set<TEntity>().FindAsync(Id);
        }

        /// <summary>
        /// 按条件查询
        /// </summary>
        /// <param name="Id"></param>
        /// <returns></returns>
        public async Task<TEntity> FindAsync(Expression<Func<TEntity, bool>> predicate)
        {
            return await db.Set<TEntity>().FirstOrDefaultAsync(predicate);
        }

        /// <summary>
        /// 查全部
        /// </summary>
        /// <param name="Id"></param>
        /// <returns></returns>
        public async Task<List<TEntity>> QueryAsync()
        {
            return await db.Set<TEntity>().ToListAsync();
        }

        /// <summary>
        /// 查全部
        /// </summary>
        /// <param name="Id"></param>
        /// <returns></returns>
        public IQueryable<TEntity> Queryable()
        {
            return db.Set<TEntity>().AsQueryable();
        }

        /// <summary>
        /// 按条件查询
        /// </summary>
        /// <param name="Id"></param>
        /// <returns></returns>
        public async Task<List<TEntity>> QueryAsync(Expression<Func<TEntity, bool>> predicate)
        {
            return await db.Set<TEntity>().Where(predicate).ToListAsync();
        }

        /// <summary>
        /// 是否存在记录
        /// </summary>
        /// <param name="Id"></param>
        /// <returns></returns>
        public async Task<bool> ExistsAsync(Expression<Func<TEntity, bool>> predicate)
        {
            return await db.Set<TEntity>().AnyAsync(predicate);
        }
    }
}
